home *** CD-ROM | disk | FTP | other *** search
- Path: mail2news.demon.co.uk!genesis.demon.co.uk
- From: Lawrence Kirby <fred@genesis.demon.co.uk>
- Newsgroups: comp.lang.c
- Subject: Re: A little shift to the left and a little shift to the right.
- Date: Sat, 13 Apr 96 13:42:01 GMT
- Organization: none
- Message-ID: <829402921snz@genesis.demon.co.uk>
- References: <4knegm$40d@crl.crl.com>
- Reply-To: fred@genesis.demon.co.uk
- X-NNTP-Posting-Host: genesis.demon.co.uk
- X-Newsreader: Demon Internet Simple News v1.27
- X-Mail2News-Path: genesis.demon.co.uk
-
- In article <4knegm$40d@crl.crl.com> smuegge@crl.com "Shad Muegge" writes:
-
- >Our trusty PL/M-to-C translator generated the C operators << and >>
- >whenever it encountered the PL/M operators SHL and SHR.
-
- I wouldn't call it so 'trusty'!
-
- >In one case the original coder had used these bit shifting operators
- >to clear out the top nibble of a byte using the following code.
- >(Actually this is the C code the translator generated less the
- >proprietary variable names. :))
- >
- > x = ( ( y << 4 ) >> 4 );
- >
- > (The name of the coder will remain a secret, and yes I know a
- > simple "& 0x0f" would be a more obvious solution. but the same
- > problem is exhibited for any left-shift followed by a right-shift)
-
- & 0x0f assumes 8 bit bytes, but maybe PL/M does guarantee that (although
- C doesn't).
-
- >Both the variables x and y are bytes ( unsigned chars ).
- >
- >The results of this code is the the value of y is assigned to
- >x without any modification. The same results as simple assignment
- >(x = y). It turns out that every C compiler I've tried ( Intel-C,
- >Microsoft VC++, and gcc) exhibits this same behaviour.
-
- That is the correct behaviour on those systems. The >> and << operators
- define that 'the integral promotions' are performed on their operands.
- Therefore an unsigned char operand is first promoted to int (or just
- possibly unsigned int) and the result has that same type. Your PL/M to C
- converter is in error here (assuming PL/M doesn't do any implicit
- widening).
-
- >Looking at the assembly code generated by all three compilers the
- >reason the shifts have no effect is because they do them with 32
- >bit registers. So, when the bits are shifted to the left by 4 they
- >aren't "lost" as one might expect. Then the right shift just
- >returns all the bits to original position.
-
- That is what should happen where int is at least 4 bits wider than char
- (or at least 5 bits if you don't want to hit sign bit issues). On systems
- with 8 bit chars that is guaranteed (since ints must be at least 16 bits).
-
- >By using a typecast two of the compilers (Intel-C and gcc) will
- >do what the original coder intended, mask off the the top nibble of
- >a byte. Microsoft's compiler just ignored the typecast and
- >generated the same code as it did without the typecast.
- >
- > x = ( ( unsigned char ) ( y << 4 ) >> 4 );
-
- That is correct code since the intermediate result is forced to an
- unsigned char and hence the top 4 bits from the original value are cleared.
- If your Microsoft compiler doesn't do this correctly then it is broken.
-
- Coincidentally I have a SCO system here which has gcc, cc (Microsoft) and
- icc (Intel) compilers on it. All worked correctly with that code, in fact
- it was only the Intel optimising compiler that didn't spot the optimisation
- to y & 0x0f.
-
- --
- -----------------------------------------
- Lawrence Kirby | fred@genesis.demon.co.uk
- Wilts, England | 70734.126@compuserve.com
- -----------------------------------------
-